home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DS-CD ROM 2 1993 August
/
DS CD-ROM 2.Ausgabe (August 1993).iso
/
programm
/
ds0334
/
sim51_04.arj
/
SERIELL.A51
< prev
next >
Wrap
Text File
|
1991-02-25
|
6KB
|
227 lines
$noMod51 ; schaltet die beim ASM51 sonst default definierten
; SFR-Declarations für den 8051 aus
$noList ; folgender Teil des Source erscheint nicht im List-
; File. Sinnvoll hier, um den langen Include-File,
; nicht in List aufzunehmen.
$INCLUDE(a:\reg52.pdf) ; Inhalt aus dem File wird hier eingefügt. Dort stehen
; die SFR-Declarationen für den 8052
$list ; obige "noList" - Direktrive wieder aufheben.
; ****** zur Assemblierung mit ASM51.EXE (von Intel) oder A51.EXE (von Keil)
; oben stehen Assembler-Direktriven. Hier als Beispiel zum Einfügen der
; SFR-Deklarationen für eine 8052 CPU.
; Proceduren zur seriellen Datenübertragung:
;-------------------------------------------
; Hier wird als Beispiel mit absoluten Segmenten gearbeitet.
; Es sind Proceduren realisiert, die Daten vom seriellen Port empfangen
; - mit zwischenpufferung im internen RAM. Der eigentliche Empfang geht
; per Interrupt.
; Senden soll direkt (ohne Interrupt) erfolgen.
USING 0 ; Register-Bank 0 reservieren
USING 1 ; Register-Bank 1 reservieren
ARxBufWrite DATA 08 ; Inhalt von Register-Bank 1 auch über DATA-
RxBufWrite SET R0 ; Adressen ansprechbar
ARxBufRead DATA 09
RxBufRead SET R1
BSEG ; (AT 0) Bit-Adressen 00...07 in DATA-Byte 20h
TxEmpty: DBIT 1
ISEG AT 21h
RxBuffer: DS 30 ; Zwischenpuffer für Receive über Interrupt
RxBufTop:
stack: DS 20 ; Platz für Stack reservieren
;-----------------------------------------------------------------------------
; ***** hier Einsprung bei Reset
CSEG ;( da erste CSEG-Direktrive = CSEG AT 0000)
JMP init
;------------------------------------------------------------------------------
; **** hier steht die Interrupt-Routine für seriellen Port
CSEG AT SINT ; SINT CODE 0023h vordefiniert in ASM51
JNB RI, sIntChkTx ; wenn RI=0, dann kein receive Interr.
PUSH PSW
MOV PSW, #08 ; Reg-Bank 1 wählen, damit nicht PUSH
MOV R7, A ; nötig zum Sichern
MOV A, RxBufRead
CJNE A, #RxBuffer, chkRxBufFull
MOV A, #RxBufTop
chkRxBufFull:
DEC A ; nun @A auf Byte vor @Read-Pointer
CJNE A, ARxBufWrite, RxBufEintrag
CLR REN
SJMP RxSintRet ; wenn Read-Pointer 1 Byte über Write-
; Pointer, kein Eintrag, REN löschen
; RI aber freigeben, da sonst wieder
; Interrupt.
RxBufEintrag:
MOV A, SBUF
MOV @RxBufWrite, A ; eintragen
INC RxBufWrite ; nächstes Byte im Ringbuffer
CJNE RxBufWrite, #RxBufTop, RxSintRet
MOV RxBufWrite, #RxBuffer ; erstes Byte des Ringbuffes
RxSintRet:
CLR RI
MOV A, R7
POP PSW
sIntChkTx:
JNB TI, sIntRet ; wenn TI=0, dann kein Transmit
SETB TxEmpty ; Flag setzen
CLR TI ; damit Interrupt-Bedingung weg
sIntRet:
RETI
;------------------------------------------------------------------------------
; ***** Procedure für Empfang eines Zeichens (Austrag aus Ringbuffer RxBuffer)
; warte, wenn noch keines empfangen wurde
getChar:
MOV A, ARxBufRead
getCharWait: ; warte bis Zeichen empfangen
CJNE A, ARxBufWrite, RxAustragen
JMP getCharWait
RxAustragen:
MOV R0, A
MOV A, @R0 ; Zeichen auslesen
INC R0 ; Read-Pointer auf nächstes
CJNE R0, #RxBufTop, getCharRet
MOV R0, #RxBuffer ; Ringbuffer-Anfang
getCharRet:
MOV ARxBufRead, R0 ; Pointer ablegen
SETB REN ; falls zuvor Buffer voll war
RET ; siehe Sint
;------------------------------------------------------------------------------
; ***** Procedure zum Senden eines Zeichens (warte, wenn Buffer voll)
sendChar:
JNB TxEmpty, $ ; TxEmpty Flag wird in SInt Routine
MOV SBUF, A ; gesetzt. TI kann nicht selbst ver-
CLR TxEmpty ; wendet werden, da dies einen Inter-
RET ; rupt auslöst.
;------------------------------------------------------------------------------
; **** hier Initialisierung nach Reset.
init:
CLR A
MOV PSW, A ; eigentlich schon durch Hardware
MOV TCON, A ; aber hier zur Verdeutlichung nochmal
MOV IE, A ; weil wichtig und für Software-Reset
MOV SCON, A
MOV SP, #(stack-1)
MOV TMOD, #20h ; Timer1 als 8 Bit Timer mit Auto-Reload
MOV TH1, #0FDh ; Vorladewert für Timer1 - damit zählen:
MOV TL1, TH1 ; FD, FE, FF, FD, ... (Teiler durch 3)
ORL PCON, #80h ; mit SMOD = 1 kein weiterer Teiler durch 2, d.h. das
; DPLL für seriell Port wird jeden 6ten CPU-
; Cyclus incrementiert. Da DPLL 16stellig,
; und 1 CPU-Cyclus = 1/12 Oszillator-Takt
; ergibt sich als Baud-Rate:
; Oszillator ÷ 12 ÷ 3 ÷ 16 das sind
; 19200 Baud bei 11.0592 MHz Oszillator
SETB TR1 ; starte Timer 1
MOV SCON, #40h ; seriell Mode1: 8 bit UART mit Timer1 für BR
MOV IE, #90h ; seriellen Interrupt freigeben
SETB TxEmpty ; Transmit Leer
MOV ARxBufWrite, #RxBuffer
MOV ARxBufRead, #RxBuffer
SETB REN ; Receiver Enable
;----------------------------------------------------------------------------
; ***** Initialisierung fertig, nun Hauptprogramm
MOV DPTR, #TxString
MOV R1, #(TxStringEnd - TxString) ; Länge
sendTxString:
CLR A
MOVC A, @A+DPTR
INC DPTR
CALL sendChar
DJNZ R1, sendTxString
warteEingabe:
CALL getChar
CJNE A, #03, echoChar ; CTRL-C = asci03
CLR EA ; Interrupts sperren
MOV DPTR, #jmpReset
PUSH DPL
PUSH DPH
RETI ; Sprung zu reset über 2x RETI,
jmpReset: ; damit Interrupt-Logik zurück-
MOV DPTR, #reset ; gesetzt
PUSH DPL
PUSH DPH
RETI
echoChar:
CALL sendChar
CJNE A, #13, warteEingabe ; bei Carriage Return zusätzlich
MOV A, #10 ; Line Feed beim Echo
CALL sendChar
JMP warteEingabe
TxString: DB 13,10,'**** Seriell Transmit Test mit 19200 Baud:',13,10
DB 13,10,'ab nun werden alle eingegebenen Zeichen als'
DB ' Echo zur',129,'ckgeschrieben.'
DB 13,10,'CTRL-C f',129,'hrt zu einem Reset:',13,10
TxStringEnd:
; leider kennt der Assembler 'ü' nicht, deßhalb oben asc129 eingegben
; 10 = 0Ah = Line Feed, 13 = 0Dh = Carrige Return
END